﻿using System;
using System.Collections.Generic;
using ServiceClient.CalendarService;
using ServiceClient.RoomService;
using ServiceClient.UserService;
using WebMvc.Models;

namespace ServiceClient
{
    public class OpenMeetingsServiceClient
    {
        private const long LanguageId = 8; // 8 = Español
        private const int NroDeParticipantes = 10;
        private const string ExternalRoomType = "Probando";
        private const string User = "soap";
        private const string Pass = "1234";

        private readonly UserServicePortTypeClient _userService;
        private readonly RoomServicePortTypeClient _roomService;
        private readonly CalendarServicePortTypeClient _calendarService;

        private string _currentToken;

        public OpenMeetingsServiceClient()
        {
            _userService = new UserServicePortTypeClient();
            _roomService = new RoomServicePortTypeClient();
            _calendarService = new CalendarServicePortTypeClient();
        }

        public string CurrentToken
        {
            get
            {
                if (string.IsNullOrEmpty(_currentToken))
                {
                    _currentToken = GetNewToken();
                    Login(_currentToken, User, Pass);
                }

                return _currentToken;
            }
        }

        public void Login(string token, string user, string pass)
        {
            var result = _userService.loginUser(token, user, pass);

            if (result < 0)
                throw new Exception(GetErrorMessage(result));
        }

        // Crea la sala
        public void CreateNewRoom(string name, int roomType, string comment)
        {
            var result = _roomService.addRoomWithModerationAndExternalType(CurrentToken, name, roomType, comment,
                NroDeParticipantes, true, true, false, 0, false, ExternalRoomType);

            if (result < 0)
                throw new Exception(GetErrorMessage(result));
        }

        // Obtiene el id de la sala
        public long GetRoomId(string name, int roomType, string comment, long externalRoomId)
        {
            var result = _roomService.getRoomIdByExternalId(CurrentToken, name, roomType, comment, NroDeParticipantes,
                false, false, false, 0, false, externalRoomId, ExternalRoomType);

            if (result < 0)
                throw new Exception(GetErrorMessage(result));

            return result;
        }

        public string GetRoomUrl(long roomId)
        {
            var hash = _userService.setUserObjectAndGenerateRoomHash(CurrentToken, "Cesar", "Cesar", "Sandrigo", null,
                "cmsandrigo@prueba.com", "cmsandrigo", ExternalRoomType, roomId, 0, 0);

            if (hash.Length < 32)
            {
                int errCode;
                if (int.TryParse(hash, out errCode))
                    throw new Exception(GetErrorMessage(errCode));
                
                throw new Exception("No se pudo obtener el mensaje de error. Hash: " + hash);
            }

            return "http://swf3.connectis-ict.com.ar:5080/openmeetings/?secureHash=" + hash;
        }

        // Crea la sala
        public void CreateNewRoom(Sala sala)
        {
            var result = _roomService.addRoomWithModerationAndExternalType(CurrentToken, sala.Nombre, (int)sala.Tipo, sala.Comentario,
                sala.CantidadParticipantes, sala.EsPublica, sala.ParaCitarse, sala.ParaDemo, sala.DuracionDemo, sala.SalaModerada, sala.TipoExterno);

            if (result < 0)
                throw new Exception(GetErrorMessage(result));
        }

        // Retorna el id
        public long GetRoomId(Sala sala)
        {
            var result = _roomService.getRoomIdByExternalId(CurrentToken, sala.Nombre, (int)sala.Tipo, sala.Comentario,
                sala.CantidadParticipantes, sala.EsPublica, sala.ParaCitarse, sala.ParaDemo, sala.DuracionDemo, sala.SalaModerada, sala.Id, sala.TipoExterno);

            if (result < 0)
                throw new Exception(GetErrorMessage(result));

            return result;
        }

        public string GetInvitationHash(Sala sala, string usrNombre, string usrApellido, string usrMail, bool moderador)
        {
            if (!sala.IdOpenMeetings.HasValue)
                throw new Exception("La sala no tiene seteado el ID de OpenMeetings.");

            var hash = _userService.setUserObjectAndGenerateRoomHash(CurrentToken, usrNombre, usrNombre, usrApellido, null,
                usrMail, usrNombre, sala.TipoExterno, sala.IdOpenMeetings.Value, moderador ? 1 : 0, 0);

            if (hash.Length < 32)
            {
                int errCode;
                if (int.TryParse(hash, out errCode))
                    throw new Exception(GetErrorMessage(errCode));

                throw new Exception("No se pudo obtener el mensaje de error. Hash: " + hash);
            }

            return "http://swf3.connectis-ict.com.ar:5080/openmeetings/?secureHash=" + hash;
        }

        public Dictionary<long, int> GetActiveUsers(int[] roomIds)
        {
            var counters = new Dictionary<long, int>();

            if (roomIds.Length < 1)
                return counters;

            var result = _roomService.getRoomCounters(CurrentToken, roomIds);

            foreach (var r in result)
                counters.Add(r.roomId, r.roomCount.HasValue ? r.roomCount.Value : 0);

            return counters;
        }

        public int GetActiveUsers(int roomId)
        {
            var result = _roomService.getRoomCounters(CurrentToken, new []{ roomId });

            if (result.Length < 1)
                return 0;

            return result[0].roomCount.HasValue ? result[0].roomCount.Value : 0;
        }


        public long CreateNewAppointment(long roomId, string nombre, string lugar, string descripcion,
            RepeticionEvento repeticion, DateTime desde, DateTime hasta, int roomType)
        {
            var result = _calendarService.saveAppointment(CurrentToken, nombre, lugar, descripcion, desde, hasta,
                repeticion == RepeticionEvento.Diariamente,
                repeticion == RepeticionEvento.Semanalmente,
                repeticion == RepeticionEvento.Mensualmente,
                repeticion == RepeticionEvento.Anualmente,
                1, // Categoría (1, la unica que existe)
                3, // Tipo de notificación (Ical)
                new[] { "'1,Cesar,Sandrigo,csandrigo@folderit.net,3,Etc/GMT-3'" }, //"2,Adrian,Carrizo,adrian.carrizo@connectis-ict.com.ar,3,Etc/GMT-3"
                roomType, LanguageId, false, null, roomId);

            if (result < 0)
                throw new Exception(GetErrorMessage(result));

            return result;
        }

        private string GetNewToken()
        {
            var data = _userService.getSession();
            return data.session_id;
        }

        private string GetErrorMessage(long errorCode)
        {
            var err = _userService.getErrorByCode(CurrentToken, errorCode, LanguageId);

            return err == null
                ? "No se pudo obtener el mensaje de error."
                : string.Format("{0}: {1}.", err.errortype, err.errmessage);
        }
    }
}